﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using MxDrawXLib;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using CommandLine;

namespace Json2Dwg
{
    public static class Program
    {
        public static string DEFAULT_XDATA_APPNAME = "VENTANALY_APPNAME";
        public static string CUSTOM_ENTITY_FIELDS_DICT_KEY = "VENTANALY_FIELDS_DICT_KEY";
        public static string ERROR_FILE = "Json2Dwg.err";

        public static bool IsJObjectType(object value)
        {
            bool ret = false;
            try
            {
                JObject _value = (JObject)value;
                ret = true;
            }
            catch (Exception)
            {
                ret = false;
            }
            return ret;
        }

        public static bool IsJArrayType(object value)
        {
            bool ret = false;
            try
            {
                JArray _value = (JArray)value;
                ret = true;
            }
            catch (Exception)
            {
                ret = false;
            }
            return ret;
        }

        public static MxDrawMcCmColor JsonToCadColor(JObject obj)
        {
            if (!obj.ContainsKey("ColorMethod") || !obj.ContainsKey("ColorIndex") || !obj.ContainsKey("EntityColor"))
            {
                throw new Exception("convert json to cad color faield");
            }
            MxDrawMcCmColor _color = new MxDrawMcCmColor();
            _color.colorIndex = obj["ColorIndex"].ToObject<int>();
            _color.ColorMethod = (MCAD_McColorMethod)obj["ColorIndex"].ToObject<int>();
            _color.EntityColor = obj["EntityColor"].ToObject<int>();
            return _color;
        }

        public static MxDrawPoint JsonToCadPoint(JObject obj)
        {
            if (!obj.ContainsKey("x") || !obj.ContainsKey("y"))
            {
                throw new Exception("convert json to cad point failed");
            }
            MxDrawPoint _pt = new MxDrawPoint();
            _pt.x = obj["x"].ToObject<double>();
            _pt.y = obj["y"].ToObject<double>();
            if (obj.ContainsKey("z"))
            {
                _pt.z = obj["z"].ToObject<double>();
            }
            return _pt;
        }


        public static MxDrawVector3d JsonToCadVector(JObject obj)
        {
            if (!obj.ContainsKey("x") || !obj.ContainsKey("y") || !obj.ContainsKey("z"))
            {
                throw new Exception("convert json to cad point failed");
            }
            MxDrawVector3d _v = new MxDrawVector3d();
            _v.x = obj["x"].ToObject<double>();
            _v.y = obj["y"].ToObject<double>();
            _v.z = obj["z"].ToObject<double>();
            return _v;
        }

        public static MxDrawScale3d JsonToCadScale3d(JObject obj)
        {
            if (!obj.ContainsKey("sx") || !obj.ContainsKey("sy") || !obj.ContainsKey("sz"))
            {
                throw new Exception("convert json to cad point failed");
            }
            MxDrawScale3d _v = new MxDrawScale3d();
            _v.sx = obj["sx"].ToObject<double>();
            _v.sy = obj["sy"].ToObject<double>();
            _v.sz = obj["sz"].ToObject<double>();
            return _v;
        }

        public static long GetBlockIdByName(MxDrawDatabase database, string name)
        {
            MxDrawBlockTableRecord blockTableRec = database.GetBlockTable().GetAt(name);
            if (blockTableRec == null) return 0;
            else return blockTableRec.ObjectID;
        }

        public static void SetEntityParams(MxDrawDatabase database, IMxDrawEntity ent, JObject obj)
        {
            string sType = ent.ObjectName;
            if (sType == "McDbLine")
            {
                MxDrawLine line = (MxDrawLine)ent;
                line.StartPoint = JsonToCadPoint((JObject)obj["StartPoint"]);
                line.EndPoint = JsonToCadPoint((JObject)obj["EndPoint"]);
            }
            else if (sType == "McDbCircle")
            {
                MxDrawCircle circle = (MxDrawCircle)ent;
                circle.Center = JsonToCadPoint((JObject)obj["Center"]);
                circle.Radius = obj["Radius"].ToObject<double>();
            }
            else if (sType == "McDbArc")
            {
                MxDrawArc arc = (MxDrawArc)ent;
                arc.Center = JsonToCadPoint((JObject)obj["Center"]);
                arc.Radius = obj["Radius"].ToObject<double>();
                arc.StartAngle = obj["StartAngle"].ToObject<double>();
                arc.EndAngle = obj["EndAngle"].ToObject<double>();
            }
            else if (sType == "McDbEllipse")
            {
                MxDrawEllipse ellipse = (MxDrawEllipse)ent;
                ellipse.Center = JsonToCadPoint((JObject)obj["Center"]);
                ellipse.MajorAxis = JsonToCadVector((JObject)obj["MajorAxis"]);
                //ellipse.MinorAxis = JsonToCadVector((JObject)obj["MinorAxis"]); // read-only
                ellipse.StartAngle = obj["StartAngle"].ToObject<double>();
                ellipse.EndAngle = obj["EndAngle"].ToObject<double>();
                ellipse.RadiusRatio = obj["RadiusRatio"].ToObject<double>();
            }
            else if (sType == "McDbPolyline")
            {
                MxDrawPolyline polyline = (MxDrawPolyline)ent;
                //polyline.NumVerts = obj["NumVerts"].ToObject<int>(); // read-only
                polyline.ConstantWidth = obj["ConstantWidth"].ToObject<double>();
                polyline.IsClosedStatus = obj["IsClosedStatus"].ToObject<bool>();
                polyline.Elevation = obj["Elevation"].ToObject<double>();
            }
            else if (sType == "McDbRay")
            {
                MxDrawRay ray = (MxDrawRay)ent;
                ray.basePoint = JsonToCadPoint((JObject)obj["BasePoint"]);
                ray.UnitDir = JsonToCadVector((JObject)obj["UnitDir"]);
            }
            else if (sType == "McDbXline")
            {
                MxDrawXline xline = (MxDrawXline)ent;
                xline.basePoint = JsonToCadPoint((JObject)obj["BasePoint"]);
                xline.UnitDir = JsonToCadVector((JObject)obj["UnitDir"]);
            }
            else if (sType == "McDbMline")
            {
                // 注: 该类目前不存在
            }
            else if (sType == "McDbHatch")
            {
                MxDrawHatch hatch = (MxDrawHatch)ent;
                hatch.Elevation = obj["Elevation"].ToObject<double>();
                hatch.GradientAngle = obj["GradientAngle"].ToObject<double>();
                hatch.GradientName = obj["GradientName"].ToObject<string>();
                hatch.GradientOneColorMode = obj["GradientOneColorMode"].ToObject<bool>();
                hatch.GradientType = (MCAD_GradientPatternType)obj["GradientType"].ToObject<int>();
                hatch.HatchObjectType = (MCAD_HatchObjectType)obj["HatchObjectType"].ToObject<int>();
                hatch.HatchStyle = (MCAD_HatchStyle)obj["HatchStyle"].ToObject<int>();
                //obj["NumLoops"] = hatch.NumLoops;
                hatch.PatternAngle = obj["PatternAngle"].ToObject<double>();
                hatch.PatternDouble = obj["PatternDouble"].ToObject<bool>();
                hatch.PatternName = obj["PatternName"].ToObject<string>();
                hatch.PatternScale = obj["PatternScale"].ToObject<double>();
                hatch.PatternSpace = obj["PatternSpace"].ToObject<double>();
                hatch.PatternType = (MCAD_HatchPatternType)obj["PatternType"].ToObject<int>();
                hatch.ShadeTintValue = obj["ShadeTintValue"].ToObject<double>();
            }
            else if (sType == "McDbMText")
            {
                MxDrawMText mtext = (MxDrawMText)ent;
                mtext.Contents = obj["Contents"].ToObject<string>();
                if (mtext.Contents == "")
                {
                    throw new Exception("多行文字内容为空, 不添加到模型空间");
                }
                mtext.Location = JsonToCadPoint((JObject)obj["Location"]);
                mtext.Rotation = obj["Rotation"].ToObject<double>();
                mtext.TextHeight = obj["TextHeight"].ToObject<double>();
                mtext.Width = obj["Width"].ToObject<double>();
                mtext.Attachment = (MCAD_McAttachmentPoint)obj["Attachment"].ToObject<int>();
                mtext.Direction = JsonToCadVector((JObject)obj["Direction"]);
            }
            else if (sType == "McDbText")
            {
                /*
                 摘自: 《arxdoc.chm/AcDbText/alignmentPoint》
                    This function returns the alignment point of the text. 
                    If vertical mode is AcDb::kTextBase and horizontal mode is either AcDb::kTextLeft, AcDb::kTextAlign, or AcDb::kTextFit, then the position point (DXF group code 10) is the insertion point for the text object and, 
                    for AcDb::kTextLeft, the alignment point is automatically calculated based on the other parameters in the text object. 
                    For all other vertical and horizontal mode combinations, the alignment point is used as the insertion point of the text and the position point is automatically calculated based on the other parameters in the text object.                  
                */
                MxDrawText text = (MxDrawText)ent;
                text.TextString = obj["TextString"].ToObject<string>();
                if (text.TextString == "")
                {
                    throw new Exception("单行文字内容为空, 不添加到模型空间");
                }
                text.horizontalMode = (MCAD_McHorizontalAlignment)obj["HorizontalMode"].ToObject<int>();
                text.verticalMode = (MCAD_McVerticalAlignment)obj["verticalMode"].ToObject<int>();
                text.Rotation = obj["Rotation"].ToObject<double>();
                text.Height = obj["Height"].ToObject<double>();
                text.WidthFactor = obj["WidthFactor"].ToObject<double>();
                text.Oblique = obj["Oblique"].ToObject<double>();
                if (text.verticalMode == MCAD_McVerticalAlignment.mcVerticalAlignmentBaseline && (text.horizontalMode == MCAD_McHorizontalAlignment.mcHorizontalAlignmentLeft || text.horizontalMode == MCAD_McHorizontalAlignment.mcHorizontalAlignmentAligned || text.horizontalMode == MCAD_McHorizontalAlignment.mcHorizontalAlignmentFit))
                {
                    text.Position = JsonToCadPoint((JObject)obj["Position"]);
                    // AlignmentPoint自动计算出来
                    //text.AlignmentPoint = JsonToCadPoint((JObject)obj["AlignmentPoint"]);
                }
                else
                {
                    text.AlignmentPoint = JsonToCadPoint((JObject)obj["AlignmentPoint"]);
                    // 自动计算出来
                    //text.Position = JsonToCadPoint((JObject)obj["Position"]);
                }
            }
            else if (sType == "McDbPoint")
            {
                MxDrawPointEntity point = (MxDrawPointEntity)ent;
                point.Position = JsonToCadPoint((JObject)obj["Position"]);
            }
            else if (sType == "McDbProxyEntity")
            {
                MxDrawProxyEntity proxyEnt = (MxDrawProxyEntity)ent;
                //proxyEnt.originalClassName = obj["originalClassName"].ToObject<string>(); // read-only
            }
            else if (sType == "McDbCustomEntity")
            {
                MxDrawCustomEntity customEnt = (MxDrawCustomEntity)ent;
                customEnt.Guid = obj["Guid"].ToObject<string>();
            }
            else if (sType == "McDbRasterImage")
            {
                MxDrawRasterImage image = (MxDrawRasterImage)ent;
                image.ImageDefId = obj["ImageDefId"].ToObject<long>();
            }
            else if (sType == "McDbSolid")
            {
                MxDrawSolid soild = (MxDrawSolid)ent;
            }
            else if (sType == "McDbSpline")
            {
                MxDrawSpline spline = (MxDrawSpline)ent;
            }
            else if (sType == "McDbTrace")
            {
                MxDrawTrace trace = (MxDrawTrace)ent;
            }
            else if (sType == "McDbWipeout")
            {
                // 该类目前不存在
            }
            else if (sType == "McDbDimAligned")
            {
                // 对齐标注
                MxDrawDimAligned dim = (MxDrawDimAligned)ent;
                // 共有属性
                dim.DimensionStyle = obj["DimensionStyle"].ToObject<string>();
                dim.DimensionText = obj["DimensionText"].ToObject<string>();
                dim.Elevation = obj["Elevation"].ToObject<double>();
                dim.HorizontalRotation = obj["HorizontalRotation"].ToObject<double>();
                dim.TextAttachment = (MCAD_McAttachmentPoint)obj["TextAttachment"].ToObject<int>();
                dim.TextPosition = JsonToCadPoint((JObject)obj["TextPosition"]);
                dim.TextRotation = obj["TextRotation"].ToObject<double>();
                dim.UsingDefaultTextPosition = obj["UsingDefaultTextPosition"].ToObject<bool>();
                // 特有属性
                dim.DimLinePoint = JsonToCadPoint((JObject)obj["DimLinePoint"]);
                dim.Oblique = obj["Oblique"].ToObject<double>();
                dim.XLine1Point = JsonToCadPoint((JObject)obj["XLine1Point"]);
                dim.XLine2Point = JsonToCadPoint((JObject)obj["XLine2Point"]);
            }
            else if (sType == "McDbDimRadial")
            {
                // 半径标注
                MxDrawDimRadial dim = (MxDrawDimRadial)ent;
                // 共有属性
                dim.DimensionStyle = obj["DimensionStyle"].ToObject<string>();
                dim.DimensionText = obj["DimensionText"].ToObject<string>();
                dim.Elevation = obj["Elevation"].ToObject<double>();
                dim.HorizontalRotation = obj["HorizontalRotation"].ToObject<double>();
                dim.TextAttachment = (MCAD_McAttachmentPoint)obj["TextAttachment"].ToObject<int>();
                dim.TextPosition = JsonToCadPoint((JObject)obj["TextPosition"]);
                dim.TextRotation = obj["TextRotation"].ToObject<double>();
                dim.UsingDefaultTextPosition = obj["UsingDefaultTextPosition"].ToObject<bool>();
                // 特有属性
                dim.Center = JsonToCadPoint((JObject)obj["Center"]);
                dim.ChordPoint = JsonToCadPoint((JObject)obj["ChordPoint"]);
                dim.ExtArcStartAngle = obj["ExtArcStartAngle"].ToObject<double>();
                dim.ExtArcEndAngle = obj["ExtArcEndAngle"].ToObject<double>();
                dim.LeaderLength = obj["LeaderLength"].ToObject<double>();
            }
            else if (sType == "McDbDimDiametric")
            {
                // 直径标注
                MxDrawDimDiametric dim = (MxDrawDimDiametric)ent;
                // 共有属性
                dim.DimensionStyle = obj["DimensionStyle"].ToObject<string>();
                dim.DimensionText = obj["DimensionText"].ToObject<string>();
                dim.Elevation = obj["Elevation"].ToObject<double>();
                dim.HorizontalRotation = obj["HorizontalRotation"].ToObject<double>();
                dim.TextAttachment = (MCAD_McAttachmentPoint)obj["TextAttachment"].ToObject<int>();
                dim.TextPosition = JsonToCadPoint((JObject)obj["TextPosition"]);
                dim.TextRotation = obj["TextRotation"].ToObject<double>();
                dim.UsingDefaultTextPosition = obj["UsingDefaultTextPosition"].ToObject<bool>();
                // 特有属性
                dim.ChordPoint = JsonToCadPoint((JObject)obj["ChordPoint"]);
                dim.FarChordPoint = JsonToCadPoint((JObject)obj["FarChordPoint"]);
                dim.LeaderLength = obj["LeaderLength"].ToObject<double>();
            }
            else if (sType == "McDbDimRotated")
            {
                // 旋转标注
                MxDrawDimRotated dim = (MxDrawDimRotated)ent;
                // 共有属性
                dim.DimensionStyle = obj["DimensionStyle"].ToObject<string>();
                dim.DimensionText = obj["DimensionText"].ToObject<string>();
                dim.Elevation = obj["Elevation"].ToObject<double>();
                dim.HorizontalRotation = obj["HorizontalRotation"].ToObject<double>();
                dim.TextAttachment = (MCAD_McAttachmentPoint)obj["TextAttachment"].ToObject<int>();
                dim.TextPosition = JsonToCadPoint((JObject)obj["TextPosition"]);
                dim.TextRotation = obj["TextRotation"].ToObject<double>();
                dim.UsingDefaultTextPosition = obj["UsingDefaultTextPosition"].ToObject<bool>();
                // 特有属性
                dim.DimLinePoint = JsonToCadPoint((JObject)obj["DimLinePoint"]);

                dim.Oblique = obj["Oblique"].ToObject<double>();
                dim.Rotation = obj["Rotation"].ToObject<double>();
                dim.XLine1Point = JsonToCadPoint((JObject)obj["XLine1Point"]);
                dim.XLine2Point = JsonToCadPoint((JObject)obj["XLine2Point"]);
            }
            else if (sType == "McDbDimAngular")
            {
                // 二维角度标注
                MxDrawDimAngular dim = (MxDrawDimAngular)ent;
                // 共有属性
                dim.DimensionStyle = obj["DimensionStyle"].ToObject<string>();
                dim.DimensionText = obj["DimensionText"].ToObject<string>();
                dim.Elevation = obj["Elevation"].ToObject<double>();
                dim.HorizontalRotation = obj["HorizontalRotation"].ToObject<double>();
                dim.TextAttachment = (MCAD_McAttachmentPoint)obj["TextAttachment"].ToObject<int>();
                dim.TextPosition = JsonToCadPoint((JObject)obj["TextPosition"]);
                dim.TextRotation = obj["TextRotation"].ToObject<double>();
                dim.UsingDefaultTextPosition = obj["UsingDefaultTextPosition"].ToObject<bool>();
                // 特有属性
                dim.ArcPoint = JsonToCadPoint((JObject)obj["ArcPoint"]);
                dim.XLine1Start = JsonToCadPoint((JObject)obj["XLine1Start"]);
                dim.XLine1End = JsonToCadPoint((JObject)obj["XLine1End"]);
                dim.XLine2Start = JsonToCadPoint((JObject)obj["XLine2Start"]);
                dim.XLine2End = JsonToCadPoint((JObject)obj["XLine2End"]);
            }
            else if (sType == "McDbAttributeDefinition")
            {
                MxDrawAttributeDefinition attrDef = (MxDrawAttributeDefinition)ent;
                // MxDrawText公共属性
                attrDef.Position = JsonToCadPoint((JObject)obj["Position"]);
                attrDef.TextString = obj["TextString"].ToObject<string>();
                attrDef.Rotation = obj["Rotation"].ToObject<double>();
                attrDef.Height = obj["Height"].ToObject<double>();
                attrDef.WidthFactor = obj["WidthFactor"].ToObject<double>();
                attrDef.AlignmentPoint = JsonToCadPoint((JObject)obj["AlignmentPoint"]);
                attrDef.horizontalMode = (MCAD_McHorizontalAlignment)obj["HorizontalMode"].ToObject<int>();
                attrDef.verticalMode = (MCAD_McVerticalAlignment)obj["verticalMode"].ToObject<int>();
                attrDef.Oblique = obj["Oblique"].ToObject<double>();
                // MxDrawAttributeDefinition特有属性
                attrDef.IsConstant = obj["IsConstant"].ToObject<bool>();
                attrDef.IsInvisible = obj["IsInvisible"].ToObject<bool>();
                attrDef.Tag = obj["Tag"].ToObject<string>();
                attrDef.Prompt = obj["Prompt"].ToObject<string>();
            }
            else if (sType == "McDbAttribute")
            {
                MxDrawAttribute attrib = (MxDrawAttribute)ent;
                // MxDrawText公共属性
                attrib.Position = JsonToCadPoint((JObject)obj["Position"]);
                attrib.TextString = obj["TextString"].ToObject<string>();
                attrib.Rotation = obj["Rotation"].ToObject<double>();
                attrib.Height = obj["Height"].ToObject<double>();
                attrib.WidthFactor = obj["WidthFactor"].ToObject<double>();
                attrib.AlignmentPoint = JsonToCadPoint((JObject)obj["AlignmentPoint"]);
                attrib.horizontalMode = (MCAD_McHorizontalAlignment)obj["HorizontalMode"].ToObject<int>();
                attrib.verticalMode = (MCAD_McVerticalAlignment)obj["verticalMode"].ToObject<int>();
                attrib.Oblique = obj["Oblique"].ToObject<double>();
                // MxDrawAttribute特有属性
                //attrib.IsConstant = obj["IsConstant"].ToObject<bool>(); // read-only
                attrib.IsInvisible = obj["IsInvisible"].ToObject<bool>();
                attrib.Tag = obj["Tag"].ToObject<string>();
            }
            else if (sType == "McDbBlockReference")
            {
                MxDrawBlockReference blkRef = (MxDrawBlockReference)ent;
                //blkRef.AttributeCount = obj["AttributeCount"].ToObject<int>(); // read-only
                blkRef.BlockTableRecordId = GetBlockIdByName(database, obj["blockName"].ToObject<string>());
                if (blkRef.BlockTableRecordId == 0)
                {
                    throw new Exception("引用的块不存在或被删除, 删除该块引用");
                }
                blkRef.Position = JsonToCadPoint((JObject)obj["Position"]);
                blkRef.Rotation = obj["Rotation"].ToObject<double>();
            }
            else
            {
                // 其它图元, 后续再补充完善
            }
        }

        public static void HackSetEntityParams(MxDrawDatabase database, IMxDrawEntity ent, JObject obj)
        {
            string sType = ent.ObjectName;
            // 特殊处理多段线
            if (sType == "McDbPolyline")
            {
                JArray startWidths = (JArray)obj["startWidths"];
                JArray endWidths = (JArray)obj["endWidths"];
                JArray bulges = (JArray)obj["bulges"];
                JArray points = (JArray)obj["points"];

                MxDrawPolyline polyline = (MxDrawPolyline)ent;
                for (int i = 0; i < points.Count; i++)
                {
                    polyline.AddVertexAt(JsonToCadPoint((JObject)points[i]), bulges[i].ToObject<double>(), startWidths[i].ToObject<double>(), endWidths[i].ToObject<double>());
                }
            }
            else if (sType == "McDbHatch")
            {
                MxDrawHatch hatch = (MxDrawHatch)ent;
                JArray loops = (JArray)obj["loops"];
                JArray patterns = (JArray)obj["patterns"];
                for (int i = 0; i < loops.Count; i++)
                {
                    JObject _loop = (JObject)loops[i];
                    int loopType = _loop["loopType"].ToObject<int>();
                    JArray points = (JArray)_loop["points"];
                    JArray bulges = (JArray)_loop["bulges"];

                    if (obj.ContainsKey("PatternAngle"))
                    {
                        hatch.PatternAngle = obj["PatternAngle"].ToObject<double>();
                    }
                    var loop = new MxDrawResbuf();
                    for (int j = 0; j < points.Count; j++)
                    {
                        var pt = JsonToCadPoint((JObject)points[j]);
                        loop.AddPoint(pt);
                        loop.AddDouble(bulges[j].ToObject<double>());
                    }
                    hatch.AppendLoop(loopType, loop);
                }
                if (obj.ContainsKey("Elevation"))
                {
                    hatch.Elevation = obj["Elevation"].ToObject<double>();
                }
                // 增加图案定义数据
                for (int i = 0; i < patterns.Count; i++)
                {
                    var _pattern = (JObject)patterns[i];
                    double angle = _pattern["angle"].ToObject<double>();
                    double baseX = _pattern["baseX"].ToObject<double>();
                    double baseY = _pattern["baseY"].ToObject<double>();
                    double offsetX = _pattern["offsetX"].ToObject<double>();
                    double offsetY = _pattern["offsetY"].ToObject<double>();
                    JArray dashes = (JArray)_pattern["dashes"];
                    MxDrawResbuf defData = new MxDrawResbuf();
                    foreach (var val in dashes)
                    {
                        defData.AddDouble(val.ToObject<double>());
                    }
                    hatch.AddPatternDefinition(angle, baseX, baseY, offsetX, offsetY, defData);
                }
            }
            else if (sType == "McDbBlockReference")
            {
                MxDrawBlockReference blkRef = (MxDrawBlockReference)ent;

                var blockName = obj["blockName"].ToObject<string>();
                if (blockName.StartsWith("A$"))
                    blkRef.BlockTableRecordId = 0;
                if (blockName.Length > 0)
                {
                    var blockTableRec = database.GetBlockTable().GetAt(blockName, false);
                    if (blockTableRec != null)
                    {
                        blkRef.BlockTableRecordId = blockTableRec.ObjectID;
                    }
                }
                // 删除多余的字段
                //   DELETE_OBJECT_KEYS(obj, ["blockName"])
                if (blkRef.BlockTableRecordId == 0)
                {
                    throw new Exception(string.Format("无法找到{0}块定义!", blockName));
                }

                // 设置缩放因子和变换矩阵
                JObject ScaleFactors = (JObject)obj["ScaleFactors"];
                JArray BlockTransform = (JArray)obj["BlockTransform"];

                var _ScaleFactors = JsonToCadScale3d(ScaleFactors);
                var _BlockTransform = new MxDrawMatrix3d();
                for (short i = 0; i < 4; i++)
                {
                    JArray row = (JArray)BlockTransform[i];
                    for (short j = 0; j < 4; j++)
                    {
                        _BlockTransform.Set(i, j, row[j].ToObject<double>());
                    }
                }
                blkRef.ScaleFactors = _ScaleFactors;
                blkRef.BlockTransform = _BlockTransform;
            }
            else if (sType == "McDbSpline")
            {
                MxDrawSpline spline = (MxDrawSpline)ent;
                // 拟合方式
                if (obj.ContainsKey("fitPoints"))
                {
                    JArray fitPoints = (JArray)obj["fitPoints"];
                    JObject startTangent = (JObject)obj["startTangent"];
                    JObject endTangent = (JObject)obj["endTangent"];
                    if (fitPoints == null || fitPoints.Count < 3)
                    {
                        throw new Exception("样条曲线[fitPoints]数据缺失!");
                    }
                    var _fitPoints = new MxDrawPoints();
                    foreach (var _pt in fitPoints)
                    {
                        _fitPoints.Add2(JsonToCadPoint((JObject)_pt));
                    }

                    var _startTangent = JsonToCadVector((JObject)startTangent);
                    var _endTangent = JsonToCadVector((JObject)endTangent);
                    spline.SetFitData(_fitPoints, 0, 0, _startTangent, _endTangent);
                }
                else if (obj.ContainsKey("ctrlPoints"))
                {
                    // 控制点方式
                    JArray ctrlPoints = (JArray)obj["ctrlPoints"];
                    JArray weights = (JArray)obj["weights"];
                    JArray knots = (JArray)obj["knots"];
                    bool closed = obj["closed"].ToObject<bool>();
                    if (ctrlPoints == null || ctrlPoints.Count < 3)
                    {
                        throw new Exception("样条曲线[ctrPoints]数据缺失!");
                    }
                    var _ctrlPoints = new MxDrawPoints();
                    foreach (var _pt in ctrlPoints)
                    {
                        _ctrlPoints.Add2(JsonToCadPoint((JObject)_pt));
                    }

                    var _weights = new MxDrawResbuf();
                    foreach (var val in weights)
                    {
                        _weights.AddDouble(val.ToObject<double>());
                    }
                    var _knots = new MxDrawResbuf();
                    foreach (var val in knots)
                    {
                        _knots.AddDouble(val.ToObject<double>());
                    }
                    spline.SetNurbsData(
                        3, // 3次样条
                        false, // 是否rational
                        closed, // 是否闭合
                        false, // 是否周期性
                        _ctrlPoints,
                        _knots,
                        _weights,
                        1e-4, // 误差精度
                        1e-4 // 误差精度
                    );
                }
            }
            else if (sType == "McDbSolid")
            {
                MxDrawSolid solid = (MxDrawSolid)ent;
                JArray points = (JArray)obj["points"];
                for (int i = 0; i < points.Count; i++)
                {
                    solid.SetPointAt(i, JsonToCadPoint((JObject)points[i]));
                }
            }
        }

        public static MxDrawDictionary GetExtDict(IMxDrawEntity ent)
        {
            MxDrawDictionary dict = ent.GetExtensionDictionary();
            if (dict == null)
            {
                ent.SetProp("createExtensionDictionary", new MxDrawResbuf());
                dict = ent.GetExtensionDictionary();
            }
            return dict;
        }

        public static void HACK_CUSTOM_ENTITY_FIELDS_TO_EXT_DICT(IMxDrawEntity ent, JObject fields)
        {
            MxDrawDictionary dict = GetExtDict(ent);
            var obj = dict.GetAt(CUSTOM_ENTITY_FIELDS_DICT_KEY);
            if (obj == null)
            {
                // 新建(注意: AddXRecord会自动将key变成大写!!!)
                var xRecord = dict.AddXRecord(CUSTOM_ENTITY_FIELDS_DICT_KEY);
                // 写入字段信息
                var ret = new MxDrawResbuf();
                // 保存为json字符串格式
                ret.AddString(JsonConvert.SerializeObject(fields));
                xRecord.SetXRecordData(ret);
            }
        }

        public static void SetEntityDatas(IMxDrawEntity ent, JObject obj)
        {
            MxDrawDictionary dict = GetExtDict(ent);
            foreach (var item in obj)
            {
                string key = item.Key;
                string uKey = key.ToUpper();
                JToken value = item.Value;
                MxDrawXRecord xRecord = (MxDrawXRecord)dict.GetAt(uKey, false);
                if (xRecord == null)
                {
                    xRecord = dict.AddXRecord(uKey);
                }
                var ret = new MxDrawResbuf();
                ret.AddString(JsonConvert.SerializeObject(new JObject() {
                    new JProperty("field", key),
                    new JProperty("value", value)
                }));
                xRecord.SetXRecordData(ret);
            }
        }

        public static IMxDrawEntity BuildEntityFromJsonData(MxDrawDatabase database, MxDrawBlockTableRecord blockTableRec, JObject obj)
        {
            string sType = obj["objectName"].ToObject<string>();
            // 忽略点图元(不可见, 还会导致图形缩放比例不正确)
            if (sType == "McDbPoint") return null;

            IMxDrawEntity ent = null;
            long objId = 0;
            if (sType.StartsWith("McDb"))
            {
                // 内置图元
                if (sType == "McDbArc")
                {
                    // HACK 创建一个位于圆点，半径为1的半圆弧
                    // 如果直接AddEntity得到一个圆弧ent, 再修改属性时, 应遵循 Center > Radius的顺序, 否则ocx控件会崩溃
                    ent = blockTableRec.AddArc(0, 0, 1, 0, Math.PI);
                }
                else if (sType == "McDbEllipse")
                {
                    ent = blockTableRec.AddEllipseArc(0, 0, 100, 0, 0.6, 0, 180);
                }
                else
                {
                    ent = blockTableRec.AddEntity(sType);
                }
                if (ent != null)
                {
                    objId = ent.ObjectID;
                    try
                    {
                        // 图元的traits
                        ent.Layer = obj["layer"].ToObject<string>();
                        ent.LineType = obj["lineType"].ToObject<string>();
                        ent.colorIndex = (MCAD_COLOR)obj["colorIndex"].ToObject<int>();
                        ent.Lineweight = (MCAD_LWEIGHT)obj["lineWeight"].ToObject<int>();
                        ent.TrueColor = JsonToCadColor(JObject.Parse(obj["trueColor"].ToObject<string>()));
                        // 图元几何参数
                        JObject _params = (JObject)obj["params"];
                        HackSetEntityParams(database, ent, _params);
                        SetEntityParams(database, ent, _params);
                        // 图元的属性属性(扩展词典)
                        JObject datas = (JObject)obj["datas"];
                        SetEntityDatas(ent, datas);
                    }
                    catch (Exception ee)
                    {
                        Console.WriteLine("删除{0}图元, 原因:{1}", sType, ee.Message);
                        // 删除图元
                        ent.Erase();
                        ent = null;
                        objId = 0;
                    }
                }
            }
            else
            {
                // 自定义图元
                // 调用AddCustomEntity函数绘制自定义实体
                // 逗号后的字符串是自定义实体的GUID
                MxDrawResbuf ret = blockTableRec.GetProp(string.Format("AddCustomEntity,{0}", sType));
                if (ret != null)
                {
                    // 得到自定义实体。
                    objId = ret.AtObjectId(0);
                    MxDrawCustomEntity customEnt = (MxDrawCustomEntity)database.ObjectIdToObject(objId);
                    ent = customEnt;

                    try
                    {
                        // 图元的traits
                        ent.Layer = obj["layer"].ToObject<string>();
                        ent.LineType = obj["lineType"].ToObject<string>();
                        ent.colorIndex = (MCAD_COLOR)obj["colorIndex"].ToObject<int>();
                        ent.Lineweight = (MCAD_LWEIGHT)obj["lineWeight"].ToObject<int>();
                        ent.TrueColor = JsonToCadColor(JObject.Parse(obj["trueColor"].ToObject<string>()));

                        // 图元几何参数
                        JObject _params = (JObject)obj["params"];
                        // 记录字段类型信息
                        JObject fields = new JObject();
                        customEnt.BeginSetValue();
                        foreach (var item in _params)
                        {
                            string key = item.Key;
                            JToken value = item.Value;
                            if (value.Type == JTokenType.Float)
                            {
                                customEnt.SetDouble(key, value.ToObject<double>());
                                fields[key] = (int)FieldType.FLOAT;
                            }
                            else if (value.Type == JTokenType.Integer)
                            {
                                customEnt.SetLong(key, value.ToObject<int>());
                                fields[key] = (int)FieldType.INT;
                            }
                            else if (value.Type == JTokenType.String)
                            {
                                customEnt.SetString(key, value.ToObject<string>());
                                fields[key] = (int)FieldType.STRING;
                            }
                            else if (value.Type == JTokenType.Boolean)
                            {
                                customEnt.SetLong(key, value.ToObject<bool>() ? 1 : 0);
                                fields[key] = (int)FieldType.BOOLEAN;
                            }
                            else if (value.Type == JTokenType.Object)
                            {
                                // 判断是否点类型
                                JObject pt = (JObject)value;
                                if (pt.ContainsKey("x") && pt.ContainsKey("y"))
                                {
                                    customEnt.SetPoint(key, JsonToCadPoint(pt));
                                    fields[key] = (int)FieldType.POINT;
                                }
                                else
                                {
                                    // 其它类型都转为字符串
                                    customEnt.SetString(key, JsonConvert.SerializeObject(value));
                                    fields[key] = (int)FieldType.STRING;
                                }
                            }
                            else
                            {
                                // 其它类型都转为字符串
                                customEnt.SetString(key, JsonConvert.SerializeObject(value));
                                fields[key] = (int)FieldType.STRING;
                            }
                        }
                        customEnt.EntSetValue();
                        // 图元的几何参数字段信息写入到特殊词典
                        HACK_CUSTOM_ENTITY_FIELDS_TO_EXT_DICT(ent, fields);
                        // 图元的属性属性(扩展词典)
                        JObject datas = (JObject)obj["datas"];
                        SetEntityDatas(ent, datas);
                    }
                    catch (Exception ee)
                    {
                        Console.WriteLine("删除{0}图元, 原因:{1}", sType, ee.Message);
                        // 删除图元
                        ent.Erase();
                        ent = null;
                        objId = 0;
                    }

                }
            }
            return ent;
        }

        public static void ClearBlock(MxDrawBlockTableRecord blockTableRec)
        {
            // 清空块
            MxDrawBlockTableRecordIterator iter = blockTableRec.NewIterator();
            for (; !iter.Done(); iter.Step(true, true))
            {
                MxDrawEntity ent = iter.GetEntity();
                ent.Erase();
            }
            System.Runtime.InteropServices.Marshal.ReleaseComObject(iter);
        }

        public static void BuildEntitiesFromJsonData(MxDrawDatabase database, MxDrawBlockTableRecord blockTableRec, JArray entities)
        {
            // 清空块
            ClearBlock(blockTableRec);
            // 向块中添加图元
            BuildEntitiesFromJsonDataRecursive(database, blockTableRec, entities);
        }

        public static void BuildEntitiesFromJsonDataRecursive(MxDrawDatabase database, MxDrawBlockTableRecord blockTableRec, JArray entities)
        {
            // 重新向块中添加图元
            foreach (var item in entities)
            {
                try
                {
                    if (item.Type == JTokenType.Array)
                    {
                        JArray _entities = (JArray)item;
                        BuildEntitiesFromJsonDataRecursive(database, blockTableRec, _entities);
                    }
                    else if (item.Type == JTokenType.String)
                    {
                        // 解压缩(base64 decode -> unGzip)
                        string jsonStr = ZipUtil.GZipDecompressString(item.ToObject<string>());
                        // json反序列化
                        object value = JsonConvert.DeserializeObject(jsonStr);
                        if (IsJArrayType(value))
                        {
                            BuildEntitiesFromJsonDataRecursive(database, blockTableRec, (JArray)value);
                        }
                        else if (IsJObjectType(value))
                        {
                            BuildEntityFromJsonData(database, blockTableRec, (JObject)value);
                        }
                    }
                    else if (item.Type == JTokenType.Object)
                    {
                        BuildEntityFromJsonData(database, blockTableRec, (JObject)item);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("[ERROR]BuildEntitiesFromJsonDataRecursive: {0}", e.Message);
                }
            }
        }

        public static void BuildDatabaseFromJsonData(MxDrawDatabase database, JObject obj)
        {
            database.CurrentlyColorIndex = (MCAD_COLOR)obj["currentlyColorIndex"].ToObject<int>();
            database.CurrentlyDimstyleName = obj["currentlyDimstyleName"].ToObject<string>();
            database.CurrentlyLayerName = obj["currentlyLayerName"].ToObject<string>();
            database.CurrentlyLineTypeName = obj["currentlyLineTypeName"].ToObject<string>();
            database.CurrentlyLineTypeScale = obj["currentlyLineTypeScale"].ToObject<double>();
            database.CurrentlyTextStyle = obj["currentlyTextStyle"].ToObject<string>();
            database.CurrentlyTrueColor = JsonToCadColor(JObject.Parse(obj["currentlyTrueColor"].ToObject<string>()));
            database.Insbase = JsonToCadPoint(JObject.Parse(obj["insbase"].ToObject<string>()));
            database.LinetypeScale = obj["lineTypeScale"].ToObject<double>();
        }

        public static long GetLineTypeIdByName(MxDrawDatabase database, string name)
        {
            MxDrawLinetypeTableRecord lineTypeTableRec = database.GetLinetypeTable().GetAt(name);
            if (lineTypeTableRec == null) return 0;
            else return lineTypeTableRec.ObjectID;
        }

        public static void BuildLayersFromJsonData(MxDrawDatabase database, JArray datas)
        {
            MxDrawLayerTable layerTable = database.GetLayerTable();
            foreach (var item in datas)
            {
                try
                {
                    JObject obj = (JObject)item;
                    MxDrawLayerTableRecord layerTableRec = null;
                    string name = obj["name"].ToObject<string>();
                    //if (name == "0")
                    //{
                    //    // 0图层默认存在，不能新建, 只能修改
                    //    layerTableRec = layerTable.GetAt(name, false);
                    //}
                    if (layerTable.Has(name))
                    {
                        layerTableRec = layerTable.GetAt(name, false);
                    }
                    else
                    {
                        layerTableRec = layerTable.Add(name);
                    }
                    if (layerTableRec == null) continue;

                    //layerTableRec.Name = name;
                    layerTableRec.Color = JsonToCadColor(JObject.Parse(obj["color"].ToObject<string>()));
                    layerTableRec.IsFrozen = obj["isFrozen"].ToObject<bool>();
                    layerTableRec.IsLocked = obj["isLocked"].ToObject<bool>();
                    layerTableRec.IsOff = obj["isOff"].ToObject<bool>();
                    layerTableRec.LinetypeObjectId = GetLineTypeIdByName(database, name);
                    layerTableRec.Lineweight = (MCAD_LWEIGHT)obj["lineWeight"].ToObject<int>();
                }
                catch (Exception e)
                {
                    Console.WriteLine("[ERROR]BuildLayersFromJsonData: {0}", e.Message);
                }
            }
        }

        public static void BuildLineTypesFromJsonData(MxDrawDatabase database, JArray datas)
        {
            MxDrawLinetypeTable lineTypeTable = database.GetLinetypeTable();
            foreach (var item in datas)
            {
                try
                {
                    JObject obj = (JObject)item;

                    MxDrawLinetypeTableRecord lineTypeTableRec = null;
                    string name = obj["name"].ToObject<string>();
                    //if (name == "ByLayer" || name == "ByBlock" || name == "Continuous")
                    //{
                    //    lineTypeTableRec = lineTypeTable.GetAt(name, false);
                    //}

                    if (lineTypeTable.Has(name))
                    {
                        lineTypeTableRec = lineTypeTable.GetAt(name, false);
                    }
                    else
                    {
                        lineTypeTableRec = lineTypeTable.Add(name);
                    }
                    if (lineTypeTableRec == null) continue;

                    //lineTypeTableRec.Name = name;
                    lineTypeTableRec.Comments = obj["comments"].ToObject<string>();
                    lineTypeTableRec.NumDashes = obj["numDashes"].ToObject<int>();

                    JArray dashes = (JArray)JsonConvert.DeserializeObject(obj["dashes"].ToObject<string>());
                    // 注: ByLayer、ByBlock、Continuous的dashes都为空
                    for (int i = 0; i < dashes.Count; i++)
                    {
                        lineTypeTableRec.SetDashLengthAt(i, dashes[i].ToObject<double>());
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("[ERROR]BuildLineTypesFromJsonData: {0}", e.Message);
                }
            }
        }

        public static void BuildTextStylesFromJsonData(MxDrawDatabase database, JArray datas)
        {
            MxDrawTextStyleTable textStyleTable = database.GetTextStyleTable();
            foreach (var item in datas)
            {
                try
                {
                    JObject obj = (JObject)item;

                    MxDrawTextStyleTableRecord textStyleTableRec = null;
                    string name = obj["name"].ToObject<string>();
                    //if (name == "Standard")
                    //{
                    //    textStyleTableRec = textStyleTable.GetAt(name, false);
                    //}

                    if (textStyleTable.Has(name))
                    {
                        textStyleTableRec = textStyleTable.GetAt(name, false);
                    }
                    else
                    {
                        textStyleTableRec = textStyleTable.Add(name);
                    }
                    if (textStyleTableRec == null) continue;

                    string typeface = obj["typeface"].ToObject<string>();
                    var bold = obj["bold"].ToObject<bool>();
                    var italic = obj["italic"].ToObject<bool>();
                    var charset = obj["charset"].ToObject<int>();
                    var pitchAndFamily = obj["pitchAndFamily"].ToObject<int>();
                    if (typeface.Length > 0)
                    {
                        // 设置文字的TrueType字体
                        textStyleTableRec.SetFont(typeface, bold, italic, charset, pitchAndFamily);
                    }
                    textStyleTableRec.bigFontFileName = obj["bigFontFileName"].ToObject<string>();
                    textStyleTableRec.fileName = obj["fileName"].ToObject<string>();
                    textStyleTableRec.isShapeFile = obj["isShapeFile"].ToObject<bool>();
                    textStyleTableRec.isVertical = obj["isVertical"].ToObject<bool>();
                    textStyleTableRec.obliquingAngle = obj["obliquingAngle"].ToObject<double>();
                    textStyleTableRec.textSize = obj["textSize"].ToObject<int>();
                }
                catch (Exception e)
                {
                    Console.WriteLine("[ERROR]BuildTextStylesFromJsonData: {0}", e.Message);
                }
            }
        }

        public static void BuildDimStylesFromJsonData(MxDrawDatabase database, JArray datas)
        {
            // 读取标注变量json配置文件
            JObject DimStyleVariables = JObject.Parse(File.ReadAllText("DimVars.json"));

            MxDrawDimStyleTable dimStyleTable = database.GetDimStyleTable();
            foreach (var item in datas)
            {
                try
                {
                    JObject obj = (JObject)item;

                    MxDrawDimStyleTableRecord dimStyleTableRec = null;
                    string name = obj["name"].ToObject<string>();
                    //if (name == "Standard" || name == "ISO-25" || name == "Annotative")
                    //{
                    //    dimStyleTableRec = dimStyleTable.GetAt(name, false);
                    //}
                    if (dimStyleTable.Has(name))
                    {
                        dimStyleTableRec = dimStyleTable.GetAt(name, false);
                    }
                    else
                    {
                        dimStyleTableRec = dimStyleTable.Add(name);
                    }
                    if (dimStyleTableRec == null) continue;

                    JObject vars = (JObject)obj["vars"];
                    foreach (var _item in DimStyleVariables)
                    {
                        string _name = _item.Key;
                        JObject _var = (JObject)_item.Value;
                        var code = _var["code"].ToObject<int>();
                        var type = _var["type"].ToObject<string>();
                        var value = _var["value"];
                        try
                        {
                            if (type == "int")
                            {
                                dimStyleTableRec.SetDimVarInt(code, vars[_name].ToObject<int>());
                            }
                            else if (type == "double")
                            {
                                dimStyleTableRec.SetDimVarDouble(code, vars[_name].ToObject<double>());
                            }
                            else if (type == "string")
                            {
                                dimStyleTableRec.SetDimVarString(code, vars[_name].ToObject<string>());
                            }
                        }
                        catch (Exception)
                        {
                            if (type == "int")
                            {
                                dimStyleTableRec.SetDimVarInt(code, value.ToObject<int>());
                            }
                            else if (type == "double")
                            {
                                dimStyleTableRec.SetDimVarDouble(code, value.ToObject<double>());
                            }
                            else if (type == "string")
                            {
                                dimStyleTableRec.SetDimVarString(code, value.ToObject<string>());
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("[ERROR]BuildDimStylesFromJsonData: {0}", e.Message);
                }
            }
        }


        // 词典辅助工具类
        public static void SetAllDictionaryDataCall(MxDrawDictionary dict, JObject data)
        {
            foreach (var item in data)
            {
                string key = item.Key;
                if (dict.GetAt(key, false) != null)
                {
                    dict.Remove(key);
                }
                JToken value = item.Value;
                if (value.Type == JTokenType.Object)
                {
                    MxDrawDictionary myDict = (MxDrawDictionary)dict.AddObject(key, "McDbDictionary");
                    SetAllDictionaryDataCall(myDict, (JObject)value);
                }
                else
                {
                    // json字符串
                    MxDrawResbuf res = null;
                    try
                    {
                        res = new MxDrawResbuf();
                        object _value = JsonConvert.DeserializeObject((string)value);
                        if (IsJArrayType(_value))
                        {
                            JArray values = (JArray)_value;
                            foreach (var val in values)
                            {
                                res.AddString(val.ToObject<string>());
                            }
                        }
                        else
                        {
                            res.AddString((string)value);
                        }
                    }
                    catch (Exception)
                    {
                        res = null;
                    }

                    if (res != null)
                    {
                        MxDrawXRecord rec = dict.AddXRecord(key);
                        // 设置扩展记录数据。
                        rec.SetXRecordData(res);
                    }
                }
            }
        }

        public static void BuildDictsFromJsonData(MxDrawDatabase database, JArray datas)
        {
            var nodDict = database.GetNamedObjectsDictionary();
            foreach (var item in datas)
            {
                try
                {
                    JObject obj = (JObject)item;
                    string name = obj["name"].ToObject<string>();
                    MxDrawDictionary myDict = (MxDrawDictionary)nodDict.GetAt(name, false);
                    if (myDict == null)
                    {
                        myDict = (MxDrawDictionary)nodDict.AddObject(name, "McDbDictionary");
                    }
                    if (myDict == null) continue;

                    JObject key_values = (JObject)obj["key_values"];
                    if (key_values != null)
                    {
                        SetAllDictionaryDataCall(myDict, key_values);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("[ERROR]BuildDictsFromJsonData: {0}", e.Message);
                }
            }
        }

        public static void BuildBlocksFromJsonData(MxDrawDatabase database, JArray datas)
        {
            var blockTable = database.GetBlockTable();
            foreach (var item in datas)
            {
                try
                {
                    MxDrawBlockTableRecord blockTableRec = null;
                    JObject obj = (JObject)item;
                    string name = obj["name"].ToObject<string>();
                    JArray entities = (JArray)obj["entities"];
                    if (entities.Count == 0)
                    {
                        Console.WriteLine($"忽略空块{name}");
                        continue;
                    }

                    //if (name == "*Model_Space" || name == "*Paper_Space" || name == "*Paper_Space0")
                    //{
                    //    blockTableRec = blockTable.GetAt(name, false);
                    //}

                    if (blockTable.Has(name))
                    {
                        blockTableRec = blockTable.GetAt(name, false);
                    }
                    else
                    {
                        blockTableRec = blockTable.Add(name);
                    }
                    if (blockTableRec == null) continue;

                    blockTableRec.Origin = JsonToCadPoint(JObject.Parse(obj["origin"].ToObject<string>()));
                    // 向块中添加图元
                    BuildEntitiesFromJsonData(database, blockTableRec, entities);
                }
                catch (Exception)
                {
                }
            }
        }


        public static JObject MakeJsonResult(int code, object data, string msg)
        {
            return new JObject()
            {
                new JProperty("code", code),
                new JProperty("data", data),
                new JProperty("msg", msg),
            };
        }
        //public static JObject MakeJsonResult(int code, JObject data, string msg)
        //{
        //    return new JObject()
        //    {
        //        {"code", code },
        //        {"data", data },
        //        {"msg", msg }
        //    };
        //}

        public class Options
        {

            [Option("json", Required = true, HelpText = "input json file")]
            public string JsonFile { get; set; }

            [Option("dwg", Required = true, HelpText = "output dwg file")]
            public string DwgFile { get; set; }

            [Option('o', "out", Required = false, Default = null, HelpText = "write a new dwg file")]
            public string OutFile { get; set; }

            [Option("without-database", Required = false, Default = false, HelpText = "disable write database")]
            public bool WithoutDatabase { get; set; }

            [Option("without-layer", Required = false, Default = false, HelpText = "disable write layers")]
            public bool WithoutLayer { get; set; }

            [Option("without-linetype", Required = false, Default = false, HelpText = "disable write linetypes")]
            public bool WithoutLineType { get; set; }

            [Option("without-textstyle", Required = false, Default = false, HelpText = "disable write text styles")]
            public bool WithoutTextStyle { get; set; }

            [Option("without-dimstyle", Required = false, Default = false, HelpText = "disable write dim styles")]
            public bool WithoutDimStyle { get; set; }

            [Option("without-dict", Required = false, Default = false, HelpText = "disable write custom dict")]
            public bool WithoutDict { get; set; }

            [Option("without-block", Required = false, Default = false, HelpText = "disable write block definition")]
            public bool WithoutBlock { get; set; }

            [Option("without-builtin-entity", Required = false, Default = false, HelpText = "disable write builtin entities")]
            public bool WithoutBuiltinEntity { get; set; }

            [Option("without-custom-entity", Required = false, Default = false, HelpText = "disable write custom entities")]
            public bool WithoutCustomEntity { get; set; }
        }

        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        public static void Main(string[] args)
        {
            try
            {
                // 删除残留的文件
                File.Delete(ERROR_FILE);
                string dwgFile = "";
                string jsonFile = "";
                // 是否覆盖原来的dwg 或 生成新的dwg文件
                string outFile = null;
                bool withoutDatabase = false;
                bool withoutLayer = false;
                bool withoutLineType = false;
                bool withoutTextStyle = false;
                bool withoutDimStyle = false;
                bool withoutDict = false;
                bool withoutBlock = false;
                bool withoutBuiltinEntity = false;
                bool withoutCustomEntity = true; // 默认不写入自定义图元(目前ocx控件的支持还不完整)
                Parser.Default.ParseArguments<Options>(args)
                  .WithParsed<Options>(options =>
                  {
                      // 使用解析后的命令行参数进行操作。
                      dwgFile = options.DwgFile;
                      jsonFile = options.JsonFile;
                      if (options.OutFile != null)
                      {
                          outFile = options.OutFile;
                      }
                      if (options.WithoutDatabase)
                      {
                          withoutDatabase = true;
                      }
                      if (options.WithoutLayer)
                      {
                          withoutLayer = true;
                      }
                      if (options.WithoutLineType)
                      {
                          withoutLineType = true;
                      }
                      if (options.WithoutTextStyle)
                      {
                          withoutTextStyle = true;
                      }
                      if (options.WithoutDimStyle)
                      {
                          withoutDimStyle = true;
                      }
                      if (options.WithoutDict)
                      {
                          withoutDict = true;
                      }
                      if (options.WithoutBlock)
                      {
                          withoutBlock = true;
                      }
                      if (options.WithoutBuiltinEntity)
                      {
                          withoutBuiltinEntity = true;
                      }
                      if (options.WithoutCustomEntity)
                      {
                          withoutCustomEntity = true;
                      }
                  });

                // 创建一个无控件界面的服务器组件对象
                MxDrawService ser = new MxDrawService();

                // 打开dwg文件
                if (!ser.Open(dwgFile))
                {
                    throw new Exception(string.Format("打开文件{0}失败", dwgFile));
                }

                // 得到打开文件的数据库
                MxDrawDatabase database = ser.GetDatabase();

                JObject obj = JObject.Parse(File.ReadAllText(jsonFile));
                if (!withoutLineType)
                {
                    BuildLineTypesFromJsonData(database, (JArray)obj["lineTypes"]);
                }
                if (!withoutTextStyle)
                {
                    BuildTextStylesFromJsonData(database, (JArray)obj["textStyles"]);
                }
                if (!withoutDimStyle)
                {
                    BuildDimStylesFromJsonData(database, (JArray)obj["dimStyles"]);
                }
                if (!withoutLayer)
                {
                    BuildLayersFromJsonData(database, (JArray)obj["layers"]);
                }
                if (!withoutDict)
                {
                    BuildDictsFromJsonData(database, (JArray)obj["dicts"]);
                }
                if (!withoutBlock)
                {
                    BuildBlocksFromJsonData(database, (JArray)obj["blocks"]);
                }
                if (!withoutBuiltinEntity)
                {
                    BuildEntitiesFromJsonData(database, database.CurrentSpace(), (JArray)obj["builtinEntities"]);
                }
                if (!withoutCustomEntity)
                {
                    // BUG ocx控件会将每一个自定义图元单独生成块和块引用, 比如2条巷道会生成2个块定义*U14、*U15，以及2个块引用
                    // 在缺少自定义实体扩展的条件下, service模式也可以将自定义图元的基本特性、几何参数、属性数据写到自定义实体的[块引用]里
                    // 但最终生成的dwg文件中自定义实体的[块定义]里没有任何内容。
                    // 因此, 在Json2Dwg项目里无法将自定义实体完整的绘制出来!!!
                    // 这部分工作只能交给js来做!!!
                    BuildEntitiesFromJsonData(database, database.CurrentSpace(), (JArray)obj["customEntities"]);
                }
                if (!withoutDatabase)
                {
                    BuildDatabaseFromJsonData(database, (JObject)obj["database"]);
                }

                if (outFile != null)
                {
                    ser.SaveDwgFile(outFile);
                }
                else
                {
                    ser.SaveDwgFile(dwgFile);
                }

                // 关闭service对象
                ser.Close();
            }
            catch (Exception e)
            {
                File.WriteAllText(ERROR_FILE, e.Message);
            }

        }
    }
}